#ifndef AVALON_SERVICELOCATORSERVERTESTER_HPP
#define AVALON_SERVICELOCATORSERVERTESTER_HPP
#include <cppunit/extensions/HelperMacros.h>
#include "Avalon/IO/Channel.hpp"
#include "Avalon/IOTests/MockClientChannel.hpp"
#include "Avalon/ServiceLocator/DirectoryEntry.hpp"
#include "Avalon/ServiceLocator/ServiceLocatorServer.hpp"
#include "Avalon/ServiceLocatorTests/ServiceLocatorTests.hpp"
#include "Avalon/Services/ServiceNode.hpp"

namespace Avalon {
namespace ServiceLocator {
namespace Tests {

  /** \class ServiceLocatorServerTester
   *  \brief Tests the ServiceLocatorServer class.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class ServiceLocatorServerTester : public CPPUNIT_NS::TestFixture {
    public:

      virtual void setUp();

      virtual void tearDown();

      //! Test logging in as an account that doesn't exist.
      void TestLoginWithInvalidAccount();

      //! Test logging in with the wrong password.
      void TestLoginWithInvalidPassword();

      //! Tests a valid login.
      void TestValidLogin();

      //! Tests session authentication without logging in.
      void TestSessionAuthenticationWithoutLogin();

      //! Tests session authentication with an invalid session id.
      void TestSessionAuthenticationWithInvalidSessionId();

      //! Tests a valid session authentication.
      void TestValidSessionAuthentication();

      //! Tests session authentication after the session has expired.
      void TestExpiredSessionAuthentication();

      //! Tests registering a service without logging in.
      void TestRegisterServiceWithoutLogin();

      //! Tests registering a service.
      void TestRegisterService();

      //! Tests unregistering a service without logging in.
      void TestUnregisterServiceWithoutLogin();

      //! Tests unregistering an invalid service.
      void TestUnregisterInvalidService();

      //! Tests register/unregister together.
      void TestRegisterUnregisterService();

      //! Tests locating a service without logging in.
      void TestLocatingWithoutLogin();

      //! Tests locating a non-existing service.
      void TestLocatingNonExistingService();

      //! Tests locating a service with a single provider.
      void TestLocatingSingleProviderService();

      //! Tests locating a service with a multiple providers.
      void TestLocatingMultipleProviderService();

      //! Tests creating an account without logging in.
      void TestCreateAccountWithoutLogin();

      //! Tests creating an account without permissions.
      void TestCreateAccountWithoutPermissions();

      //! Tests creating an account using an unavailable name.
      void TestCreateAccountUnavailableName();

      //! Tests creating a valid account.
      void TestValidCreateAccount();

      //! Tests creating a directory without logging in.
      void TestCreateDirectoryWithoutLogin();

      //! Tests creating without permissions.
      void TestCreateDirectoryWithoutPermissions();

      //! Tests creating a valid directory.
      void TestValidCreateDirectory();

      //! Tests deleting an entry without logging in.
      void TestDeleteEntryWithoutLogin();

      //! Tests deleting a non-existing entry.
      void TestDeleteNonExistingEntry();

      //! Tests deleting an account without permissions.
      void TestDeleteAccountWithoutPermissions();

      //! Tests deleting an account.
      void TestDeleteAccount();

      //! Tests deleting a directory without permissions.
      void TestDeleteDirectoryWithoutPermissions();

      //! Tests deleting a directory.
      void TestDeleteDirectory();

    private:
      IO::Tests::MockServerConnection* m_serverConnection;
      MockServiceLocatorDataStore* m_dataStore;
      boost::scoped_ptr<ServiceLocatorServer> m_server;
      boost::scoped_ptr<IO::Tests::MockClientChannel> m_channel;
      IO::ConnectionState m_channelState;
      boost::scoped_ptr<Services::ServiceNode> m_service;

      void CreateUser(const std::string& username,
        const std::string& password);
      std::pair<DirectoryEntry::Tag, std::string> CreateAccountAndLogin();
      std::pair<DirectoryEntry::Tag, std::string> CreateAdditionalClient(
        boost::scoped_ptr<Services::ServiceNode>* service,
        boost::scoped_ptr<IO::Channel>* channel, const std::string& username,
        const std::string& password);

      CPPUNIT_TEST_SUITE(ServiceLocatorServerTester);
        CPPUNIT_TEST(TestLoginWithInvalidAccount);
        CPPUNIT_TEST(TestLoginWithInvalidPassword);
        CPPUNIT_TEST(TestValidLogin);
        CPPUNIT_TEST(TestSessionAuthenticationWithoutLogin);
        CPPUNIT_TEST(TestSessionAuthenticationWithInvalidSessionId);
        CPPUNIT_TEST(TestValidSessionAuthentication);
        CPPUNIT_TEST(TestExpiredSessionAuthentication);
        CPPUNIT_TEST(TestRegisterServiceWithoutLogin);
        CPPUNIT_TEST(TestRegisterService);
        CPPUNIT_TEST(TestUnregisterServiceWithoutLogin);
        CPPUNIT_TEST(TestUnregisterInvalidService);
        CPPUNIT_TEST(TestRegisterUnregisterService);
        CPPUNIT_TEST(TestLocatingWithoutLogin);
        CPPUNIT_TEST(TestLocatingNonExistingService);
        CPPUNIT_TEST(TestLocatingSingleProviderService);
        CPPUNIT_TEST(TestLocatingMultipleProviderService);
        CPPUNIT_TEST(TestCreateAccountWithoutLogin);
        CPPUNIT_TEST(TestCreateAccountWithoutPermissions);
        CPPUNIT_TEST(TestCreateAccountUnavailableName);
        CPPUNIT_TEST(TestValidCreateAccount);
        CPPUNIT_TEST(TestCreateDirectoryWithoutLogin);
        CPPUNIT_TEST(TestCreateDirectoryWithoutPermissions);
        CPPUNIT_TEST(TestValidCreateDirectory);
        CPPUNIT_TEST(TestDeleteEntryWithoutLogin);
        CPPUNIT_TEST(TestDeleteNonExistingEntry);
        CPPUNIT_TEST(TestDeleteAccountWithoutPermissions);
        CPPUNIT_TEST(TestDeleteAccount);
        CPPUNIT_TEST(TestDeleteDirectoryWithoutPermissions);
        CPPUNIT_TEST(TestDeleteDirectory);
      CPPUNIT_TEST_SUITE_END();
  };
}
}
}

#endif // AVALON_SERVICELOCATORSERVERTESTER_HPP
